package com.wstuo.common.security.dao;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Query;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

import com.wstuo.common.dao.BaseDAOImplHibernate;
import com.wstuo.common.dto.PageDTO;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.security.dto.UserQueryDTO;
import com.wstuo.common.security.entity.Organization;
import com.wstuo.common.security.entity.Role;
import com.wstuo.common.security.entity.User;
import com.wstuo.common.security.entity.UserInfoClient;
import com.wstuo.common.util.DaoUtils;
import com.wstuo.common.util.StringUtils;

/**
 * 用户DAO.
 * @author will
 */
public class UserDAO extends BaseDAOImplHibernate<User> implements IUserDAO {

	public static Integer licenseNumber = 10;
	private static final Logger LOGGER = Logger.getLogger(UserDAO.class ); 
	@Autowired
	private IRoleDAO roleDAO;

	@Autowired
	private IOrganizationDAO organizationDAO;

	/**
     * 分页查找用户数据.
     * @param qdto 查询DTO：UserQueryDTO
     * @param sord
     * @param sidx
     * @return 分页数据：PageDTO
     */
	public PageDTO findPager(UserQueryDTO qdto, String sord, String sidx) {
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		int start = 0;
		int limit = 0;
		if (qdto != null) {
			start = qdto.getStart();
			limit = qdto.getLimit();
			//查询用户条件组合
			dc = searchUserCondition(dc, qdto);
		}
		// 排序
		dc = DaoUtils.orderBy(sidx, sord, dc);
		PageDTO p = new PageDTO();
		if (StringUtils.hasText(qdto.getRoleCode())
				|| StringUtils.hasText(qdto.getBelongsGroup())
				|| (qdto.getBelongsGroupIds() != null && qdto
						.getBelongsGroupIds().length > 0)) {
			p = super.findPageByCriteria(dc, start, limit, "loginName");
		} else {
			p = super.findPageByCriteria(dc, start, limit);
		}
		return p;
	}
	/**
	 * 查找用户List数据
	 * @param qdto
	 * @param sord
	 * @param sidx
	 */
	@SuppressWarnings("unchecked")
	public List<User> findUserList(UserQueryDTO qdto, String sord, String sidx){
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		if (qdto != null) {
			//查询用户条件组合
			dc = searchUserCondition(dc, qdto);
		}
		// 排序
		dc = DaoUtils.orderBy(sidx, sord, dc);
		return super.getHibernateTemplate().findByCriteria(dc);
	}
	
	/**
	 * 查询用户条件组合
	 * @param dc
	 * @param qdto
	 */
	private DetachedCriteria searchUserCondition(DetachedCriteria dc,UserQueryDTO qdto){
		// 排除整个部门查询
		if (!StringUtils.hasText(qdto.getOrgType())&& qdto.getOrgNo() != null && qdto.getOrgNo() > 0) {
			dc.add(Restrictions.eq("orgnization.orgNo", qdto.getOrgNo()));
		}
		if (qdto.getTechnicalGroupId() != null&& qdto.getTechnicalGroupId() != 0) {
			dc.createAlias("tcGroup", "tg").add(Restrictions.eq("tg.technicalGroupId",qdto.getTechnicalGroupId()));
		}
		if (qdto.getUserState() != null) {
			dc.add(Restrictions.eq("userState", qdto.getUserState()));
		}
		if (qdto.getRoleNo() != null && qdto.getRoleNo() != 0) {
			dc.createAlias("roles", "rl").add(Restrictions.eq("rl.roleId", qdto.getRoleNo()));
		}
		if (StringUtils.hasText(qdto.getRoleCode())) {
			String[] roleCode = qdto.getRoleCode().split(";");
			if (roleCode != null && roleCode.length > 0) {
				dc.createAlias("roles", "role");
				dc.setFetchMode("roles", FetchMode.SELECT);
				dc.add(Restrictions.in("role.roleCode", roleCode));
			}
		}
		if (qdto.getLoginNames() != null && qdto.getLoginNames().length > 0) {
			dc.add(Restrictions.in("loginName", qdto.getLoginNames()));
		}
		if (StringUtils.hasText(qdto.getLoginName())) {
			dc.add(Restrictions.like("loginName", qdto.getLoginName(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getFirstName())) {
			dc.add(Restrictions.like("firstName", qdto.getFirstName(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getLastName())) {
			dc.add(Restrictions.like("lastName", qdto.getLastName(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getFullName())) {
			dc.add(Restrictions.like("fullName", qdto.getFullName(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getEmail())) {
			dc.add(Restrictions.like("email", qdto.getEmail(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getMobilePhone())) {
			dc.add(Restrictions.like("moblie", qdto.getMobilePhone(),
					MatchMode.ANYWHERE));
		}
		if (StringUtils.hasText(qdto.getOfficePhone())) {
			dc.add(Restrictions.like("phone", qdto.getOfficePhone(),
					MatchMode.ANYWHERE));
		}
		if (qdto.getCompanyNo() != null
				&& !qdto.getCompanyNo().toString().equals("-1")) {
			dc.add(Restrictions.eq("companyNo", qdto.getCompanyNo()));
		}
		// 查询整个内部部门或服务部门
		String orgType = qdto.getOrgType();
		if (StringUtils.hasText(orgType)) {
			List<Organization> organizations = new ArrayList<Organization>();
			if ("allInner".equals(orgType)) {
				organizations = organizationDAO.findBy("orgType", "inner");
			}else if ("allService".equals(orgType)) {
				organizations = organizationDAO.findBy("orgType",
						"services");
			}
			if (organizations.size() > 0) {
				dc.add(Restrictions.in("orgnization", organizations));
			} else {
				dc.add(Restrictions.eq("orgnization", null));
			}
		}
		// 所属技术组别名构造
		if ((qdto.getBelongsGroupIds() != null&& qdto.getBelongsGroupIds().length != 0)
				|| StringUtils.hasText(qdto.getBelongsGroup())) {
			dc.createAlias("belongsGroup", "bg");
		}
		// 所属技术组条件查询
		if (qdto.getBelongsGroupIds() != null&& qdto.getBelongsGroupIds().length != 0) {
			dc.setFetchMode("belongsGroup", FetchMode.SELECT);
			dc.add(Restrictions.in("bg.orgNo", qdto.getBelongsGroupIds()));
		}
		if(StringUtils.hasText(qdto.getBelongsGroup())){
			dc.add(Restrictions.like("bg.orgName", qdto.getBelongsGroup(), MatchMode.ANYWHERE));
		}
		return dc;
	}

	/**
     * 查看用户是否被禁用
     * @param userName
     * @param pwd
     * @return String
     */
	@SuppressWarnings("rawtypes")
    public String findDisable(String userName, String pwd) {
		String result = "notexist";
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Restrictions.eq("loginName", userName));
		dc.add(Restrictions.eq("password", pwd));
		dc.add(Restrictions.or(Restrictions.eq("userState", false),
				Restrictions.eq("dataFlag", Byte.parseByte("99"))));
		List list = super.getHibernateTemplate().findByCriteria(dc);
		if (list != null && list.size() > 0) {
			result = "exist";
		}
		return result;
	}

	/**
     * 用户登录.
     * @param userName
     * @param password
     * @return boolean
     */
	public Boolean userLogin(String userName, String password) {
		boolean result = false; 
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Restrictions.eq("loginName", userName).ignoreCase());
		dc.add(Restrictions.eq("password", password));
		dc.add(Restrictions.eq("userState", true));

		if ((super.getHibernateTemplate().findByCriteria(dc) != null)
				&& (super.getHibernateTemplate().findByCriteria(dc).size() > 0)) {
			result = true;
		}
		
		return result;
	}

	/**
     * 根据邮件查询用户
     * @param emails
     * @return List<User>
     */
	public List<User> findUserByEmail(String[] emails) {
		List<User> users = new ArrayList<User>();
		if (emails != null && emails.length > 0) {
			String a = "";
			for (int i = 0; i < emails.length; i++) {
				a = a + "?";
				if (i < emails.length - 1) {
					a = a + ",";
				}
			}
			String hql = "from User u where u.email in (" + a + ")";
			users = super.getHibernateTemplate().find(hql, emails);
		}
		return users;
	}

	/**
     * 根据电话、手机号码查询所有用户
     * @param qdto
     * @return List<User>
     */
	@SuppressWarnings("unchecked")
    public List<User> findUserByNumber(final UserQueryDTO qdto) {
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		Disjunction dj = Restrictions.disjunction();
		dc.add(dj);
		if (qdto != null) {
			dj.add(Restrictions.eq("moblie", qdto.getMobilePhone()));
			dj.add(Restrictions.eq("phone", qdto.getMobilePhone()));
		}
		return super.getHibernateTemplate().findByCriteria(dc);
	};

	/**
	 * 重写save方法
	 * @param entity
	 */
	@Override
	public void save(User entity) {

		Set<Role> roles = entity.getRoles();

		if (isTc(roles)
				&& !entity.getOrgnization().getOrgType().equals("itsop")) {
			// 将工程师数量加入全局
			if (licenseNumber <= countTechnician()) {
				throw new ApplicationException("TechnicianLicense_Not_Enough");
			} else {
				super.save(entity);
			}
		} else {

			super.save(entity);
		}
		// super.save(entity);
	}

	/**
     * 判断是否技术员。
     * @param roles
     * @return boolean
     */
	public boolean isTc(Set<Role> roles) {
		boolean result = false;
		if (roles != null && roles.size() > 0) {

			List<String> roleCodes = new ArrayList<String>();
			roleCodes.add("ROLE_ENDUSER");
			roleCodes.add("ROLE_ITSOP_MANAGEMENT");
			roleCodes.add("ROLE_APPROVER");

			for (Role role : roles) {
				if (role!=null && !(roleCodes.contains(role.getRoleCode()))) {
					result = true;
					break;
				}
			}
		}

		return result;

	}

	/**
	 * 重写merge方法
	 * @param entity
	 * @return User
	 */
	@Override
	public User merge(User entity) {
		Set<Role> roles = entity.getRoles();
		boolean countTc = false;
		if (isTc(roles)) {//要分配技术员的角色
			if (entity.getUserId() !=null&&entity.getUserId() != 0) {// 修改数据
				Set<Role> rolesOld = new HashSet<Role>(
						roleDAO.findByUserId(entity.getUserId()));
				if (!isTc(rolesOld)) {//新增数据
					countTc = true;
				}
			} else {// 新增数据
				countTc = true;
			}
		}
		if (countTc && licenseNumber <= countTechnician()
				&& !("itsop").equals(entity.getOrgnization().getOrgType())
				&& entity.getUserState()) {
			throw new ApplicationException("TechnicianLicense_Not_Enough");
		} else {
			return super.merge(entity);
		}
	}
	
	
	public User mergeByRoles(User entity,Set<Role> roles) {
		boolean countTc = false;
		if (isTc(roles)) {//要分配技术员的角色
			if (entity.getUserId() !=null&&entity.getUserId() != 0) {// 修改数据
				Set<Role> rolesOld = new HashSet<Role>(
						roleDAO.findByUserId(entity.getUserId()));
				if (!isTc(rolesOld)) {//新增数据
					countTc = true;
				}
				User us=super.findUniqueBy("", "");
			} else {// 新增数据
				countTc = true;
			}
		}
		if (countTc && licenseNumber <= countTechnician()
				&& !("itsop").equals(entity.getOrgnization().getOrgType())
				&& entity.getUserState()) {
			throw new ApplicationException("TechnicianLicense_Not_Enough");
		} else {
			entity.setRoles(roles);
			return super.merge(entity);
		}
	}
	public User mergeByLDAP(User entity,Set<Role> roles,Set<Role> rolesOld) {
		boolean countTc = false;
		if (isTc(roles)) {//要分配技术员的角色
			if (entity.getUserId() !=null&&entity.getUserId() != 0) {// 修改数据
				if (!isTc(rolesOld)) {//新增数据
					countTc = true;
				}
			} else {// 新增数据
				countTc = true;
			}
		}
		if (countTc && licenseNumber <= countTechnician()
				&& !("itsop").equals(entity.getOrgnization().getOrgType())
				&& entity.getUserState()) {
			throw new ApplicationException("TechnicianLicense_Not_Enough");
		} else {
			entity.setRoles(roles);
			return super.merge(entity);
		}
	}
	/**
     * 统计已经使用的技术员数量.
     * @return technician count result
     */
	public synchronized int countTechnician() {
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		// 角色
		dc.createAlias("roles", "rl");
		dc.add(Restrictions.not(Restrictions.in("rl.roleCode", new String[] {
				"ROLE_ENDUSER",
		        "ROLE_ITSOP_MANAGEMENT",
				"ROLE_APPROVER"
		})));

		dc.add(Restrictions.eq("userState", true));
		// 避免重复
		dc.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		return super.getHibernateTemplate().findByCriteria(dc).size();
	}

	/**
     * 根据用户名列表查询用户列表.
     * @param userNames
     * @return user list
     */
	@SuppressWarnings("unchecked")
	public List<User> findByUserNames(String[] userNames) {

		List<User> users = null;
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);

		if (userNames != null && userNames.length > 0) {
			dc.add(Restrictions.in("loginName", userNames));
			users = super.getHibernateTemplate().findByCriteria(dc);
		}

		return users;
	}

	/**
  	 * 根据真实姓名查找用户.
  	 * @param fullNames
  	 * @return user list
  	 */
	@SuppressWarnings("unchecked")
	public List<User> findByUserFullNames(String[] fullNames) {
		List<User> users = null;
		try {

			final DetachedCriteria dc = DetachedCriteria.forClass(User.class);

			if (fullNames != null && fullNames.length > 0) {
				dc.add(Restrictions.in("fullName", fullNames));
				users = super.getHibernateTemplate().findByCriteria(dc);
			}

		} catch (Exception ex) {

			LOGGER.error(ex.getMessage());
		}

		return users;
	}

	/**
     * 根据用户真实姓名查找是否存在。
     * @param fullName
     * @return boolean
     */
	public Boolean findByUserFullNames(String fullName) {
		boolean result = true;
		if (StringUtils.hasText(fullName)) {

			String hql = "select count(*) from User where fullName =?";
			Query query = getSession().createQuery(hql);
			query.setParameter(0, fullName);
			int count = ((Long) query.uniqueResult()).intValue();
			if (count == 0) {
				result = false;
			}
		}

		return result;
	}

	/**
     * 根据登录名查找是否存在。
     * @param loginName
     * @return boolean
     */
	public Boolean findByUserLoginName(String loginName) {
		boolean result = false;
		if (StringUtils.hasText(loginName)) {
			String hql = "select count(*) from User where loginName =?";
			Query query = getSession().createQuery(hql);
			query.setParameter(0, loginName);
			int count = ((Long) query.uniqueResult()).intValue();
			if (count > 0) {
				result = true;
			}
		}
		return result;
	}

	/**
     * 根据登录名及密码查询用户
     * @param userName
     * @param pwd
     * @return User
     */
	@SuppressWarnings("unchecked")
    public User findUserByLoginNameAndPwd(String userName, String pwd) {
		User user = null;
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Restrictions.eq("loginName", userName));
		dc.add(Restrictions.eq("password", pwd));

		List<User> list = super.getHibernateTemplate().findByCriteria(dc);

		if (list != null && list.size() > 0)
			user = list.get(0);
		
		return user;
	}

	/**
     * 根据登录名及密码查询用户
     * @param loginName
     * @return User
     */
	@SuppressWarnings("unchecked")
    public User findUserByLoginName(String loginName) {
		User user = null;
		final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Restrictions.eq("loginName", loginName));

		List<User> list = super.getHibernateTemplate().findByCriteria(dc);

		if (list != null && list.size() > 0)
			user = list.get(0);

		return user;
	}
	
	/**
	 * 分页查询技术员用户
	 * @param start
	 * @param limit
	 * @param sidx
	 * @param sord
	 * @return PageDTO
	 */
	public PageDTO findUserByTechnician(int start,int limit,String sidx,String sord){
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		// 角色
		dc.createAlias("roles", "rl");
		dc.setFetchMode("roles", FetchMode.SELECT);
		dc.add(Restrictions.not(Restrictions.in("rl.roleCode", new String[] {
				"ROLE_ENDUSER ",
				"ROLE_ITSOP_MANAGEMENT",
				"ROLE_APPROVER"
		})));
		dc.add(Restrictions.eq("userState", true));
		// 排序
		dc = DaoUtils.orderBy(sidx, sord, dc);
		return super.findPageByCriteria(dc, start, limit,"");
	}
	/**
	 * 统计技术员数量
	 */
	public Integer countUserByTechnician(){
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		// 角色
		dc.createAlias("roles", "rl");
		dc.add(Restrictions.not(Restrictions.in("rl.roleCode", new String[] {
				"ROLE_ENDUSER",
		        "ROLE_ITSOP_MANAGEMENT",
				"ROLE_APPROVER"
		})));

		// 避免重复
		dc.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		/*return super.statCriteria(dc);*/
		return super.getHibernateTemplate().findByCriteria(dc).size();
	}
	
	/**
	 * 用户是否有某个角色
	 */
	public Boolean isExistRoleByUserLoginName(String loginName,String roleCode){
		Boolean bool = false;
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Restrictions.eq("loginName", loginName));
		// 角色
		dc.createAlias("roles", "rl");
		dc.add(Restrictions.in("rl.roleCode", new String[] {
				roleCode
		}));
		List<User> list = super.getHibernateTemplate().findByCriteria(dc);
		if(list!=null && list.size()>0){
			bool = true;
		}
		return bool;
	}
	
	/**
  	 * 根据ClientId查找用户.
  	 * @param fullNames
  	 * @return user list
  	 */
	@SuppressWarnings("unchecked")
	public List<User> findByUserClientId(String clientId) {
		List<User> users = null;
		try {
			if (clientId != null && clientId.length() > 0) {
				final DetachedCriteria dcClient = DetachedCriteria.forClass(UserInfoClient.class);
				dcClient.add( Restrictions.eq("moblieClientId", clientId));
				List<UserInfoClient> clientInfos = super.getHibernateTemplate().findByCriteria(dcClient);
				if (clientInfos != null && clientInfos.size() > 0) {
					final DetachedCriteria dc = DetachedCriteria.forClass(User.class);
					dc.add(Restrictions.in("userInfoClient", clientInfos));
					users = super.getHibernateTemplate().findByCriteria(dc);
				}
			}
		} catch (Exception ex) {
			LOGGER.error(ex.getMessage());
		}
		return users;
	}
}
